import json
import os
import threading
import time
from datetime import datetime
from src.modules.file_processor import FileProcessor
from src.modules.video_processor import VideoProcessor, log_warning
from src.modules.srt_processor import SRTProcessor
from src.modules.watermark_detector import WatermarkDetector
from src.utils.util import Util
from src.utils.logger import log_info, log_error

class ClassificationController:
    def __init__(self):
        self.running = False
        self.current_task = None
        self.thread = None
        self.log_messages = []
        self.status = "idle"
        
    def process_directory(self, directory, settings):
 
        if not os.path.exists(directory):
            return {"success": False, "message": f"目录不存在: {directory}"}
        
        # 保存设置
        self.watermark_detection_var = settings.get("watermark_detection", False)
        self.ad_detection_var = settings.get("ad_detection", False)
        self.enable_translation = settings.get("enable_translation", False)
        self.enable_classification = settings.get("enable_classification", False)
        self.language_var = settings.get("language", "VN")
        self.api_key_var = settings.get("api_key", "")
        self.sleep_time = settings.get("sleep_time", 60)

        old_directory = getattr(self, 'directory', None)
        self.directory = directory
        
        if self.running:
            # 任务已在运行中，更新设置
            if old_directory == directory:
                # 相同目录，继续任务
                self._log(f"更新已运行任务的设置，继续处理目录: {directory}")
                return {"success": True, "message": f"已更新任务设置，继续处理目录: {directory}", "status": "updated"}
            else:
                # 不同目录，重新启动任务
                self._log(f"切换处理目录从 {old_directory} 到 {directory}")
                # 停止现有线程
                self.running = False
                if self.thread and self.thread.is_alive():
                    # 给线程一点时间优雅地停止
                    self.thread.join(timeout=2.0)           
                    
        # 开始异步处理
        self.running = True
        self.status = "running"
        self.thread = threading.Thread(target=self._periodic_process_directory)
        self.thread.daemon = True
        self.thread.start()
        
        return {"success": True, "message": f"开始处理目录: {directory}"}
    
    def _periodic_process_directory(self):
        """
        定期执行目录处理
        每隔 sleep_time 分钟执行一次 _process_directory_thread
        """
        while self.running:
            try:
                # 记录任务开始时间
                self._log(f"开始定期处理目录: {self.directory}")
                
                # 执行一次完整的目录处理
                self._process_directory_once()
                
                # 计算下一次运行时间
                sleep_seconds = self.sleep_time * 60  # 转换为秒
                next_run_time = datetime.now().timestamp() + sleep_seconds
                next_run_time_str = datetime.fromtimestamp(next_run_time).strftime("%Y-%m-%d %H:%M:%S")
                
                self._log(f"当前处理完成，等待下次运行... 下次运行时间: {next_run_time_str}")
                
                # 分段休眠，每10秒检查一次是否应该停止
                while self.running and time.time() < next_run_time:
                    time.sleep(min(10, next_run_time - time.time()))  # 最多休眠10秒或剩余时间
                    
            except Exception as e:
                self._log(f"定期处理过程中发生错误: {e}", level="error")
                log_error(f"定期处理错误: {e}")
                # 发生错误后暂停一分钟再试
                if self.running:
                    time.sleep(60)
        # 线程结束时确保状态正确
        self.status = "completed"
        self._log("定期处理已停止")
 
    def _process_directory_once(self):
        """
        执行一次完整的目录处理
        原来的 _process_directory_thread 方法
        """
        try:
            self._log(f"开始扫描目录: {self.directory}")
            
            # 获取包含视频的文件夹
            folders = self._get_folders_with_videos(self.directory)
            
            if not folders:
                self._log("没有找到包含视频的文件夹")
                return  # 不更改状态，让定时任务继续
            for folder in folders:
                if not self.running:
                    break
                self._log(f"处理文件夹: {folder}")
                self._process_single_folder(folder)
            self._log("本次处理完成")
            
            # 在处理完成后更新搜索索引
            self._update_search_index()
            
        except Exception as e:
            self._log(f"处理过程中发生错误: {e}", level="error")
            log_error(f"处理目录错误: {e}")

    def _process_refresh_folder(self, folder):
        """
        处理包含.refresh文件的文件夹，移动_固定水印或字幕文件夹中的视频到已处理文件夹
        
        :param folder: 要处理的文件夹路径
        """
        try:
            watermark_folder = os.path.join(folder, "_固定水印或字幕")
            processed_folder = os.path.join(folder, "_已处理")
            
            # 如果固定水印目录不存在，则无需处理
            if not os.path.exists(watermark_folder):
                self._log(f"_固定水印或字幕文件夹不存在，无需处理: {watermark_folder}")
                return
                
            # 确保已处理目录存在
            os.makedirs(processed_folder, exist_ok=True)
            self._log(f"创建或确认已处理文件夹: {processed_folder}")
            
            # 获取所有视频文件
            video_files = [f for f in os.listdir(watermark_folder) 
                        if f.lower().endswith(('.mp4', '.avi', '.mkv', '.mov'))]
            
            if not video_files:
                self._log(f"_固定水印或字幕文件夹中没有视频文件")
                return
                
            moved_count = 0
            for video_file in video_files:
                source_path = os.path.join(watermark_folder, video_file)
                target_path = os.path.join(processed_folder, video_file)
                Util.move_video_file(source_path, target_path, self._log)
                
            self._log(f"完成移动，共移动 {moved_count}/{len(video_files)} 个文件到已处理文件夹")
                    
        except Exception as e:
            self._log(f"处理.refresh文件夹时出错: {e}", level="error")
            log_error(f".refresh处理错误: {e}")

        finally:
            # 确保状态更新
            # 删除.refresh文件
            refresh_file = os.path.join(folder, ".refresh")
            if os.path.exists(refresh_file):
                try:
                    os.remove(refresh_file)
                    self._log(f"已删除.refresh文件")
                except Exception as e:
                    self._log(f"删除.refresh文件失败: {e}", level="error")
 
    def _update_search_index(self):
        """
        更新搜索索引
        """
        try:
            from src.api.controllers.search_controller import SearchController
            search_controller = SearchController()
            
            self._log("开始更新搜索索引...")
            result = search_controller.update_search_index()
            
            if result["success"]:
                self._log("搜索索引更新任务已启动")
            else:
                self._log(f"搜索索引更新失败: {result['message']}", level="warning")
                
        except Exception as e:
            self._log(f"启动搜索索引更新时出错: {e}", level="error")
            log_error(f"更新搜索索引错误: {e}")
 
    def _get_folders_with_videos(self, directory):
        """
        获取包含视频文件的文件夹列表
        :param directory: 根目录
        :return: 包含视频的文件夹列表
        """
        folders_with_videos = []

        for root, dirs, files in os.walk(directory):
            # 检查是否有视频文件
            if any(file.lower().endswith(('.mp4', '.avi', '.mkv', '.mov', '.refresh')) for file in files):
                folders_with_videos.append(root)
                self._log(f"找到包含视频的文件夹: {root}")

            # 跳过已分类的目录
            if "_固定水印或字幕" in dirs:
                self._log(f"跳过已分类的目录: {root}")
                dirs.remove("_固定水印或字幕")
            if "_已处理" in dirs:
                dirs.remove("_已处理")

        return folders_with_videos
    
    # 添加_process_single_folder方法实现

    def _process_single_folder(self, folder):
        """处理单个文件夹中的视频分类"""
        try:
            file_processor = FileProcessor(folder, status_callback=self._log)
            # 检查用户是否启用了任何功能
            if not (self.ad_detection_var or self.watermark_detection_var or
                    self.enable_translation or self.enable_classification):
                self._log("所有功能都已禁用，不进行任何操作")
                return

            video_processor = VideoProcessor(api_key=self.api_key_var, status_callback=self._log)

            # 获取当前文件夹中的所有视频文件
            video_files = [f for f in os.listdir(folder) if f.lower().endswith(('.mp4', '.avi', '.mkv', '.mov', '.flv', '.wmv', '.refresh'))]
            # 为每个视频文件进行处理
            for original_file in video_files:
                if original_file == ".refresh":
                    self._log(f"跳过特殊文件: {original_file}")
                    self._process_refresh_folder(folder=folder)
                    continue
                current_file = original_file  # 保存当前的文件名（可能会在处理过程中变化）
                file_path = os.path.join(folder, current_file)
                skip_remaining = False  # 标记是否跳过后续操作

                self._log(f"正在处理视频: {current_file}")

                # 1. 广告检测
                if self.ad_detection_var and not file_processor.is_file_processed(filename=original_file,
                                                                                attribute="advertisement"):
                    self._log(f"执行广告检测: {current_file}")
                    try:
                        # 提取字幕
                        Util.extract_subtitle(file_path)
                        srt_path = os.path.join(folder, current_file.replace(".mp4", ".srt"))

                        if os.path.exists(srt_path):
                            ad_result = SRTProcessor(srt_path=srt_path).judge_advertisement_with_openai()
                            if ad_result == "None":
                                self._log(f"视频 {current_file} 未检测到广告内容")
                                file_processor.mark_file_as_processed(filename=original_file, advertisement="未检测到广告")
                            else:
                                self._log(f"视频 {current_file} 检测到广告内容: {ad_result}")
                                file_processor.mark_file_as_processed(filename=original_file, advertisement=ad_result)

                                # 更改文件名并更新当前文件引用
                                new_file_path = os.path.join(folder, current_file + "_ad")
                                if os.path.exists(file_path) and not os.path.exists(new_file_path):
                                    Util.move_video_file(file_path, new_file_path)
                                    current_file = current_file + "_ad"
                                    file_path = new_file_path
                                    skip_remaining = True  # 有广告内容，跳过后续操作
                        else:
                            self._log(f"字幕文件不存在: {srt_path}")
                    except Exception as e:
                        self._log(f"广告检测过程中出错: {e}", level="error")
                        log_error(f"广告检测错误: {e}")

                # 2. 水印检测
                if not skip_remaining and self.watermark_detection_var and not file_processor.is_file_processed(
                        filename=original_file, attribute="watermark"):
                    self._log(f"执行水印检测: {current_file}")
                    try:
                        # 提取帧
                        frames_folder = os.path.join(folder, original_file.replace(".mp4", "_frames"))
                        video_processor.extract_frames(file_path)
                        watermark_detector = WatermarkDetector()

                        if os.path.exists(frames_folder):
                            watermark_result = watermark_detector.detect_watermark_with_ocr(frames_folder)
                            has_watermark = watermark_result.get("has_watermark", False)
                            watermark_type = watermark_result.get("type", "none")
                            watermark_text = ", ".join(watermark_result.get("texts", []))

                            if has_watermark:
                                self._log(
                                    f"视频 {current_file} 检测到 {watermark_type} 内容: {watermark_text}")
                                file_processor.mark_file_as_processed(filename=original_file,
                                                                watermark=f"{watermark_type}: {watermark_text}")
                                if watermark_type in ("固定水印", "普通字幕", "字幕"):
                                    # 创建固定水印文件夹并移动文件
                                    fixed_watermark_folder = os.path.join(folder, "_固定水印或字幕")
                                    os.makedirs(fixed_watermark_folder, exist_ok=True)
                                    new_file_path = os.path.join(fixed_watermark_folder, current_file)

                                    if os.path.exists(file_path) and not os.path.exists(new_file_path):
                                        Util.move_video_file(file_path, new_file_path)
                                        current_file = os.path.join("_固定水印或字幕", current_file)
                                        file_path = new_file_path
                                        skip_remaining = True  # 固定水印，跳过后续操作
                                else:
                                    # 移动水印，添加后缀并更新路径
                                    new_file_path = os.path.join(folder, current_file + "_watermark")
                                    if os.path.exists(file_path) and not os.path.exists(new_file_path):
                                        Util.move_video_file(file_path, new_file_path)
                                        current_file = current_file + "_watermark"
                                        file_path = new_file_path
                                        skip_remaining = True  # 移动水印，跳过后续操作
                            else:
                                self._log(f"视频 {current_file} 未检测到水印")
                                file_processor.mark_file_as_processed(filename=original_file, watermark="未检测到水印")
                        else:
                            self._log(f"帧文件夹不存在: {frames_folder}")
                    except Exception as e:
                        self._log(f"水印检测过程中出错: {e}", level="error")
                        log_error(f"水印检测错误: {e}")

                # 3. 文件名翻译 - 只有在没有水印和广告的情况下才执行
                if not skip_remaining and self.enable_translation and not file_processor.is_file_processed(
                        filename=original_file, attribute="translated_name"):
                    self._log(f"执行文件名翻译: {current_file}")
                    try:
                        file_name, ext = os.path.splitext(current_file)
                        translated_name = Util.translate_video_name(file_name, self.language_var)
                        if translated_name == None:
                            self._log(f"翻译有误，暂时跳过翻译: {current_file}")
                            continue
                        translated_name = file_processor.sanitize_filename(translated_name)
                        target_path = os.path.join(folder, translated_name + ext)
                        log_info(f"翻译后的文件名: {translated_name + ext}, 目标路径: {target_path}, 当前路径: {file_path}")
                        if os.path.exists(file_path):
                            Util.move_video_file(file_path, target_path)
                            self._log(f"文件名已翻译: {current_file} → {translated_name + ext}")
                            file_processor.mark_file_as_processed(filename=original_file,
                                                            translated_name=translated_name + ext)
                            current_file = translated_name + ext
                            file_path = target_path
                        else:
                            self._log(f"目标文件已存在或源文件不存在，跳过翻译: {file_path} → {target_path}")
                    except Exception as e:
                        self._log(f"翻译过程中出错: {e}", level="error")
                        log_error(f"翻译错误: {e}")

            # 保存处理记录
            file_processor.save_processed_files_db()

            # 4. 分类处理 - 在所有文件都处理完成后进行
            if self.enable_classification:
                # 检查是否需要跳过分类
                if file_processor.skip_classification():
                    self._log(f"没有需要分类的文件，跳过分类")
                    return

                try:
                    self._log(f"开始执行视频分类")
                    video_chunks = file_processor.get_video_files_with_types()

                    if not video_chunks or all(not chunk or len(chunk) <= 1 for chunk in video_chunks):
                        self._log(f"文件夹中没有需要处理的新视频文件: {folder}")
                    else:
                        for i, chunk in enumerate(video_chunks):
                            if not chunk or len(chunk) <= 1:  # 只有 "已有分类" 键或为空
                                continue

                            self._log(f"处理第 {i + 1}/{len(video_chunks)} 组视频 ({len(chunk)} 个文件)")

                            # 调用API进行分类
                            result = video_processor.classify_and_summarize_videos(chunk)
                            if not result:
                                self._log("分类失败，跳过此组视频")
                                continue

                            try:
                                categories = json.loads(result)
                                file_processor.organize_videos_by_category(categories)
                            except json.JSONDecodeError as e:
                                self._log(f"解析分类结果失败: {e}", level="error")
                                log_error(f"JSON解析错误: {e}")
                            except Exception as e:
                                self._log(f"组织视频文件时出错: {e}", level="error")
                                log_error(f"分类组织错误: {e}")
                except Exception as e:
                    self._log(f"分类过程中出错: {e}", level="error")
                    log_error(f"分类过程错误: {e}")

            self._log(f"文件夹 {folder} 处理完成")

        except Exception as e:
            self._log(f"处理文件夹 {folder} 时出错: {e}", level="error")
            log_error(f"处理文件夹错误: {e}")

    def _log(self, message, level="info"):
        if level == "error":
            log_error(message)
        if level == "info":
            log_info(message)
        if level == "warning":
            log_warning(message)
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = {"timestamp": timestamp, "message": message, "level": level}
        self.log_messages.append(log_entry)
        # 只保留最近1000条日志
        if len(self.log_messages) > 1000:
            self.log_messages = self.log_messages[-1000:]
    
    def get_status(self):
        return {
            "status": self.status,
            "running": self.running,
            "logs": self.log_messages,
            "current_directory": self.directory if hasattr(self, 'directory') else None
        }
    
    def stop_processing(self):
        if not self.running:
            return {"success": False, "message": "没有正在运行的任务"}
            
        self.running = False
        self._log("任务将在下一个周期结束后停止")
        
        # 等待线程结束
        if self.thread and self.thread.is_alive():
            self.thread.join(timeout=2.0)
            
        return {"success": True, "message": "任务将在下一个周期结束后停止"}